 1.模式匹配和样例类之模式匹配
   
   Scala没有Java中的switch case，它有一个更加强大的模式匹配机制，可以应用到很多场合。
   Scala的模式匹配可以匹配各种情况，比如变量的类型、集合的元素、有值或无值。
   模式匹配的基本语法结构：变量 match { case 值 => 代码 }
   模式匹配match case中，只要有一个case分支满足并处理了，就不会继续判断下一个case分支了，不
需要使用break语句。这点与Java不同，Java的switch case需要用break阻止。如果值为下划线，则代
表不满足以上所有情况的时候如何处理。
   模式匹配match case最基本的应用，就是对变量的值进行模式匹配。match是表达式，与if表达式一
样，是有返回值的。
   除此之外，Scala还提供了样例类，对模式匹配进行了优化，可以快速进行匹配。
 
 2.字符和字符串匹配
 
def main(args: Array[String]): Unit = {
  val charStr = '6'
  charStr match {
    case '+' => println("匹配上了加号")
    case '-' => println("匹配上了减号")
    case '*' => println("匹配上了乘号")
    case '/' => println("匹配上了除号")
    //注意：不满足以上所有情况，就执行下面的代码
    case _ => println("都没有匹配上，我是默认值")
  }
}

def main(args: Array[String]): Unit = {
  val arr = Array("hadoop", "zookeeper", "spark")
  val name = arr(Random.nextInt(arr.length))
  name match {
    case "hadoop" => println("大数据分布式存储和计算框架...")
    case "zookeeper" => println("大数据分布式协调服务框架...")
    case "spark" => println("大数据分布式内存计算框架...")
    case _ => println("我不认识你...")
  }
}

 3.守卫式匹配
   
// 所谓守卫就是添加if语句
object MatchDemo {
  def main(args: Array[String]): Unit = {
  //守卫式
  val character = '*'
  val num = character match {
    case '+' => 1
    case '-' => 2
    case _ if character.equals('*') => 3
    case _ => 4
  }
  println(character + " " + num)
}

 4.匹配类型
   
   Scala的模式匹配还有一个强大的功能，它可以直接匹配类型，而不是值。这一点是Java的switch case
做不到的。
   匹配类型的语法：case 变量 : 类型 => 代码，而不是匹配值的“case 值 => 代码”这种语法。
   
def main(args: Array[String]): Unit = {
  val a = 3
  val obj = if(a == 1) 1
  else if(a == 2) "2"
  else if(a == 3) BigInt(3)
  else if(a == 4) Map("aa" -> 1)
  else if(a == 5) Map(1 -> "aa")
  else if(a == 6) Array(1, 2, 3)
  else if(a == 7) Array("aa", 1)
  else if(a == 8) Array("aa")

  val r1 = obj match {
    case x: Int => x
    case s: String => s.toInt
    // case BigInt => -1 //不能这么匹配
    case _: BigInt => Int.MaxValue
    case m: Map[String, Int] => "Map[String, Int]类型的Map集合"
    case m: Map[_, _] => "Map集合"
    case a: Array[Int] => "It's an Array[Int]"
    case a: Array[String] => "It's an Array[String]"
    case a: Array[_] => "It's an array of something other than Int"
    case _ => 0
  }
  println(r1 + ", " + r1.getClass.getName)
}

 5.匹配数组、元组、集合
   
def main(args: Array[String]): Unit = {
  val arr = Array(0, 3, 5)
  //对Array数组进行模式匹配，分别匹配：
  //带有指定个数元素的数组、带有指定元素的数组、以某元素开头的数组
  arr match {
    case Array(0, x, y) => println(x + " " + y)
    case Array(0) => println("only 0")
    //匹配数组以1开始作为第一个元素
    case Array(1, _*) => println("1 ...")
    case _ => println("something else")
  }
  
  val list = List(3, -1)
  //对List列表进行模式匹配，与Array类似，但是需要使用List特有的::操作符
  //构造List列表的两个基本单位是Nil和::，Nil表示为一个空列表
  //tail返回一个除了第一元素之外的其他元素的列表
  //分别匹配：带有指定个数元素的列表、带有指定元素的列表、以某元素开头的列表
  list match {
    case x :: y :: Nil => println(s"x: $x y: $y")
    case 0 :: Nil => println("only 0")
    case 1 :: tail => println("1 ...")
    case _ => println("something else")
  }
  
  val tuple = (1, 3, 7)
  tuple match {
	case (1, x, y) => println(s"1, $x , $y")
    case (_, z, 5) => println(z)
    case _ => println("else")
  }
}

 6.样例类
   
   case class样例类是Scala中特殊的类。当声明样例类时，以下事情会自动发生：
     主构造函数接收的参数通常不需要显式使用var或val修饰，Scala会自动使用val修饰
     自动为样例类定义了伴生对象，并提供apply方法，不用new关键字就能够构造出相应的对象
     将生成toString、equals、hashCode和copy方法，除非显示的给出这些方法的定义
     继承了Product和Serializable这两个特质，也就是说样例类可序列化和可应用Product的方法

   case class是多例的，后面要跟构造参数，case object是单例的。
   此外，case class样例类中可以添加方法和字段，并且可用于模式匹配。

class Amount
//定义样例类Dollar，继承Amount父类
case class Dollar(value: Double) extends Amount
//定义样例类Currency，继承Amount父类
case class Currency(value: Double, unit: String) extends Amount
//定义样例对象Nothing，继承Amount父类
case object Nothing extends Amount

object CaseClassDemo {
  def main(args: Array[String]): Unit = {
    judgeIdentity(Dollar(10.0))
    judgeIdentity(Currency(20.2,"100"))
    judgeIdentity(Nothing)
  }
  //自定义方法，模式匹配判断amt类型
  def judgeIdentity(amt: Amount): Unit = {
    amt match {
      case Dollar(value) => println(s"$value")
      case Currency(value, unit) => println(s"Oh noes,I got $unit")
      case Nothing => println("Oh,GOD!")
    }
  }
}

 7.Option与模式匹配
   
   Scala Option选项类型用来表示一个值是可选的，有值或无值。
   Option[T] 是一个类型为 T 的可选值的容器，可以通过get()函数获取Option的值。如果值存在，
Option[T] 就是一个 Some。如果不存在，Option[T] 就是对象 None 。
   Option通常与模式匹配结合使用，用于判断某个变量是有值还是无值。

object OptionMatch {
  val grades = Map("jacky" -> 90, "tom" -> 80, "jarry" -> 95)

  def getGrade(name: String): Unit = {
    val grade = grades.get(name)
    grade match {
      case Some(grade) => println("成绩：" + grade)
      case None => println("没有此人成绩！")
    }
  }

  def main(args: Array[String]): Unit = {
    getGrade("jacky")
    getGrade("张三")
  }
}